# 个人云笔记智能诊断和自动修复脚本 (Windows)
# Personal Cloud Notes Intelligent Diagnosis and Auto-Repair Script (Windows)
# 版本: 3.0 - 融合版本

#Requires -Version 5.1
#Requires -RunAsAdministrator

param(
    [switch]$AutoFix = $false,
    [switch]$Verbose = $false,
    [switch]$ReportOnly = $false,
    [switch]$Help = $false
)

# 全局变量
$Script:LogFile = "C:\Windows\Temp\personal-cloud-notes-diagnose.log"
$Script:ReportFile = "$env:TEMP\personal-cloud-notes-diagnosis-report.json"
$Script:InstallPath = "C:\PersonalCloudNotes"
$Script:ServiceName = "PersonalCloudNotes"
$Script:DBName = "personal_cloud_notes"
$Script:IssuesFound = 0
$Script:IssuesFixed = 0

# 诊断结果存储
$Script:DiagnosisResults = @{}
$Script:RepairActions = @{}

# 颜色定义
$Script:Colors = @{
    Red = "Red"
    Green = "Green"
    Yellow = "Yellow"
    Blue = "Blue"
    Cyan = "Cyan"
    Magenta = "Magenta"
    White = "White"
}

# 显示帮助信息
function Show-Help {
    Write-Host @"
个人云笔记诊断和修复工具

用法: .\diagnose-and-fix.ps1 [参数]

参数:
  -AutoFix       自动修复发现的问题
  -Verbose       详细输出
  -ReportOnly    仅生成诊断报告，不修复
  -Help          显示此帮助信息

示例:
  .\diagnose-and-fix.ps1                # 仅诊断，不修复
  .\diagnose-and-fix.ps1 -AutoFix       # 诊断并自动修复
  .\diagnose-and-fix.ps1 -Verbose -AutoFix  # 详细模式下诊断并修复
  .\diagnose-and-fix.ps1 -ReportOnly    # 仅生成诊断报告

"@
}

# 日志函数
function Write-Log {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Level,
        [Parameter(Mandatory=$true)]
        [string]$Message
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    
    # 控制台输出
    switch ($Level) {
        "INFO" { 
            Write-Host "[INFO] $Message" -ForegroundColor $Script:Colors.Green
        }
        "WARN" { 
            Write-Host "[WARN] $Message" -ForegroundColor $Script:Colors.Yellow
        }
        "ERROR" { 
            Write-Host "[ERROR] $Message" -ForegroundColor $Script:Colors.Red
        }
        "DEBUG" { 
            if ($Verbose) {
                Write-Host "[DEBUG] $Message" -ForegroundColor $Script:Colors.Blue
            }
        }
        "SUCCESS" { 
            Write-Host "[SUCCESS] $Message" -ForegroundColor $Script:Colors.Green
        }
        "FIX" { 
            Write-Host "[FIX] $Message" -ForegroundColor $Script:Colors.Magenta
        }
    }
    
    # 写入日志文件
    try {
        Add-Content -Path $Script:LogFile -Value $logEntry -ErrorAction SilentlyContinue
    } catch {
        # 忽略日志写入错误
    }
}

# 记录诊断结果
function Record-Diagnosis {
    param(
        [string]$CheckName,
        [string]$Status,
        [string]$Details,
        [string]$FixAction = ""
    )
    
    $Script:DiagnosisResults[$CheckName] = @{
        Status = $Status
        Details = $Details
    }
    
    if ($FixAction) {
        $Script:RepairActions[$CheckName] = $FixAction
    }
    
    if ($Status -eq "FAILED") {
        $Script:IssuesFound++
    }
}

# 检查Windows服务状态
function Test-WindowsServices {
    Write-Log "INFO" "检查Windows服务状态..."
    
    $services = @("MySQL80", $Script:ServiceName, "W3SVC")
    $failedServices = @()
    
    foreach ($service in $services) {
        try {
            $svc = Get-Service -Name $service -ErrorAction SilentlyContinue
            if ($svc) {
                if ($svc.Status -eq "Running") {
                    Write-Log "DEBUG" "服务 $service 正在运行"
                    Record-Diagnosis "service_$service" "PASSED" "服务正在运行"
                } else {
                    Write-Log "WARN" "服务 $service 未运行"
                    $failedServices += $service
                    Record-Diagnosis "service_$service" "FAILED" "服务未运行" "Restart-WindowsService $service"
                }
            } else {
                Write-Log "DEBUG" "服务 $service 不存在或未安装"
            }
        } catch {
            Write-Log "ERROR" "检查服务 $service 时出错: $($_.Exception.Message)"
        }
    }
    
    if ($failedServices.Count -eq 0) {
        Write-Log "SUCCESS" "所有Windows服务运行正常"
    } else {
        Write-Log "ERROR" "发现 $($failedServices.Count) 个服务问题: $($failedServices -join ', ')"
    }
}

# 检查端口监听状态
function Test-PortListening {
    Write-Log "INFO" "检查端口监听状态..."
    
    $ports = @(80, 3000, 3306)
    $failedPorts = @()
    
    foreach ($port in $ports) {
        try {
            $connection = Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue
            if ($connection) {
                Write-Log "DEBUG" "端口 $port 正在监听"
                Record-Diagnosis "port_$port" "PASSED" "端口正在监听"
            } else {
                Write-Log "WARN" "端口 $port 未监听"
                $failedPorts += $port
                Record-Diagnosis "port_$port" "FAILED" "端口未监听" "Repair-PortIssue $port"
            }
        } catch {
            Write-Log "ERROR" "检查端口 $port 时出错: $($_.Exception.Message)"
        }
    }
    
    if ($failedPorts.Count -eq 0) {
        Write-Log "SUCCESS" "所有端口监听正常"
    } else {
        Write-Log "ERROR" "发现 $($failedPorts.Count) 个端口问题: $($failedPorts -join ', ')"
    }
}

# 检查配置文件
function Test-ConfigurationFiles {
    Write-Log "INFO" "检查配置文件..."
    
    $configFiles = @(
        "$Script:InstallPath\.env",
        "$Script:InstallPath\web.config"
    )
    
    foreach ($configFile in $configFiles) {
        $fileName = Split-Path $configFile -Leaf
        if (Test-Path $configFile) {
            if ((Get-Item $configFile).Length -gt 0) {
                Write-Log "DEBUG" "配置文件 $fileName 存在且不为空"
                Record-Diagnosis "config_$fileName" "PASSED" "配置文件存在且不为空"
                
                # 检查特定配置文件
                switch ($fileName) {
                    ".env" { Test-EnvConfig $configFile }
                    "web.config" { Test-WebConfig $configFile }
                }
            } else {
                Write-Log "WARN" "配置文件 $fileName 为空"
                Record-Diagnosis "config_$fileName" "FAILED" "配置文件为空" "Recreate-Config $configFile"
            }
        } else {
            Write-Log "ERROR" "配置文件 $fileName 不存在"
            Record-Diagnosis "config_$fileName" "FAILED" "配置文件不存在" "Recreate-Config $configFile"
        }
    }
}

# 检查.env配置文件
function Test-EnvConfig {
    param([string]$EnvFile)
    
    $requiredVars = @("DB_HOST", "DB_NAME", "DB_USER", "DB_PASSWORD", "JWT_SECRET")
    $missingVars = @()
    
    $content = Get-Content $EnvFile -ErrorAction SilentlyContinue
    
    foreach ($var in $requiredVars) {
        if (-not ($content | Where-Object { $_ -match "^$var=" })) {
            $missingVars += $var
        }
    }
    
    if ($missingVars.Count -eq 0) {
        Write-Log "DEBUG" ".env配置完整"
        Record-Diagnosis "env_config" "PASSED" ".env配置完整"
    } else {
        Write-Log "WARN" ".env配置缺少变量: $($missingVars -join ', ')"
        Record-Diagnosis "env_config" "FAILED" "缺少环境变量: $($missingVars -join ', ')" "Repair-EnvConfig"
    }
}

# 检查web.config文件
function Test-WebConfig {
    param([string]$WebConfigFile)
    
    try {
        [xml]$webConfig = Get-Content $WebConfigFile
        if ($webConfig.configuration) {
            Write-Log "DEBUG" "web.config格式正确"
            Record-Diagnosis "webconfig_syntax" "PASSED" "web.config格式正确"
        } else {
            Write-Log "ERROR" "web.config格式错误"
            Record-Diagnosis "webconfig_syntax" "FAILED" "web.config格式错误" "Repair-WebConfig"
        }
    } catch {
        Write-Log "ERROR" "web.config解析失败: $($_.Exception.Message)"
        Record-Diagnosis "webconfig_syntax" "FAILED" "web.config解析失败" "Repair-WebConfig"
    }
}

# 检查数据库连接
function Test-DatabaseConnection {
    Write-Log "INFO" "检查数据库连接..."
    
    # 检查MySQL服务
    $mysqlService = Get-Service -Name "MySQL*" -ErrorAction SilentlyContinue
    if (-not $mysqlService -or $mysqlService.Status -ne "Running") {
        Write-Log "ERROR" "MySQL服务未运行"
        Record-Diagnosis "database_service" "FAILED" "MySQL服务未运行" "Restart-MySQLService"
        return
    }
    
    # 读取数据库配置
    $envFile = "$Script:InstallPath\.env"
    if (Test-Path $envFile) {
        try {
            $envContent = Get-Content $envFile
            $dbHost = ($envContent | Where-Object { $_ -match "^DB_HOST=" }) -replace "DB_HOST=", ""
            $dbUser = ($envContent | Where-Object { $_ -match "^DB_USER=" }) -replace "DB_USER=", ""
            $dbPassword = ($envContent | Where-Object { $_ -match "^DB_PASSWORD=" }) -replace "DB_PASSWORD=", ""
            
            # 测试数据库连接
            $testQuery = "SELECT 1"
            $result = & mysql -h $dbHost -u $dbUser -p"$dbPassword" -e $testQuery $Script:DBName 2>$null
            
            if ($LASTEXITCODE -eq 0) {
                Write-Log "SUCCESS" "数据库连接正常"
                Record-Diagnosis "database_connection" "PASSED" "数据库连接正常"
            } else {
                Write-Log "ERROR" "数据库连接失败"
                Record-Diagnosis "database_connection" "FAILED" "数据库连接失败" "Repair-DatabaseConnection"
            }
        } catch {
            Write-Log "ERROR" "数据库连接测试失败: $($_.Exception.Message)"
            Record-Diagnosis "database_connection" "FAILED" "数据库连接测试失败" "Repair-DatabaseConnection"
        }
    } else {
        Write-Log "ERROR" "无法读取数据库配置"
        Record-Diagnosis "database_config" "FAILED" "无法读取数据库配置" "Recreate-EnvConfig"
    }
}

# 检查文件权限
function Test-FilePermissions {
    Write-Log "INFO" "检查文件权限..."
    
    $paths = @(
        $Script:InstallPath,
        "$Script:InstallPath\uploads",
        "$Script:InstallPath\logs",
        "$Script:InstallPath\.env"
    )
    
    foreach ($path in $paths) {
        if (Test-Path $path) {
            try {
                $acl = Get-Acl $path
                $owner = $acl.Owner
                
                Write-Log "DEBUG" "$path - 所有者: $owner"
                
                # 检查关键文件的权限
                $pathName = Split-Path $path -Leaf
                switch ($pathName) {
                    ".env" {
                        # 检查.env文件是否只有管理员可访问
                        $hasPublicAccess = $acl.Access | Where-Object { 
                            $_.IdentityReference -like "*Users*" -and $_.FileSystemRights -match "Read"
                        }
                        
                        if ($hasPublicAccess) {
                            Write-Log "WARN" ".env文件权限不安全"
                            Record-Diagnosis "permissions_env" "FAILED" ".env文件权限不安全" "Repair-EnvPermissions"
                        } else {
                            Record-Diagnosis "permissions_env" "PASSED" ".env文件权限正确"
                        }
                    }
                    default {
                        Record-Diagnosis "permissions_$pathName" "PASSED" "文件权限正确"
                    }
                }
            } catch {
                Write-Log "WARN" "检查 $path 权限时出错: $($_.Exception.Message)"
                Record-Diagnosis "permissions_$(Split-Path $path -Leaf)" "FAILED" "权限检查失败" "Repair-FilePermissions $path"
            }
        } else {
            Write-Log "WARN" "路径不存在: $path"
            Record-Diagnosis "path_$(Split-Path $path -Leaf)" "FAILED" "路径不存在" "New-MissingPath $path"
        }
    }
}

# 检查磁盘空间
function Test-DiskSpace {
    Write-Log "INFO" "检查磁盘空间..."
    
    $drives = @("C:")
    
    foreach ($drive in $drives) {
        try {
            $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$drive'"
            $freeSpaceGB = [math]::Round($disk.FreeSpace / 1GB, 2)
            $totalSpaceGB = [math]::Round($disk.Size / 1GB, 2)
            $usagePercent = [math]::Round((($disk.Size - $disk.FreeSpace) / $disk.Size) * 100, 1)
            
            Write-Log "DEBUG" "$drive 磁盘使用: $usagePercent% ($freeSpaceGB GB 可用 / $totalSpaceGB GB 总计)"
            
            if ($usagePercent -gt 90) {
                Write-Log "ERROR" "$drive 磁盘空间不足: $usagePercent%"
                Record-Diagnosis "disk_space_$($drive.Replace(':', ''))" "FAILED" "$drive 磁盘空间不足: $usagePercent%" "Invoke-DiskCleanup $drive"
            } elseif ($usagePercent -gt 80) {
                Write-Log "WARN" "$drive 磁盘空间紧张: $usagePercent%"
                Record-Diagnosis "disk_space_$($drive.Replace(':', ''))" "WARNING" "$drive 磁盘空间紧张: $usagePercent%"
            } else {
                Write-Log "DEBUG" "$drive 磁盘空间充足: $usagePercent%"
                Record-Diagnosis "disk_space_$($drive.Replace(':', ''))" "PASSED" "$drive 磁盘空间充足: $usagePercent%"
            }
        } catch {
            Write-Log "ERROR" "检查 $drive 磁盘空间时出错: $($_.Exception.Message)"
        }
    }
}

# 检查内存使用
function Test-MemoryUsage {
    Write-Log "INFO" "检查内存使用..."
    
    try {
        $memory = Get-CimInstance -ClassName Win32_ComputerSystem
        $totalMemoryGB = [math]::Round($memory.TotalPhysicalMemory / 1GB, 2)
        
        $availableMemory = Get-Counter "\Memory\Available MBytes" -SampleInterval 1 -MaxSamples 1
        $availableMemoryGB = [math]::Round($availableMemory.CounterSamples.CookedValue / 1024, 2)
        $usedMemoryGB = $totalMemoryGB - $availableMemoryGB
        $memoryUsagePercent = [math]::Round(($usedMemoryGB / $totalMemoryGB) * 100, 1)
        
        Write-Log "DEBUG" "内存使用: $usedMemoryGB GB / $totalMemoryGB GB ($memoryUsagePercent%)"
        
        if ($memoryUsagePercent -gt 90) {
            Write-Log "ERROR" "内存使用率过高: $memoryUsagePercent%"
            Record-Diagnosis "memory_usage" "FAILED" "内存使用率过高: $memoryUsagePercent%" "Optimize-MemoryUsage"
        } elseif ($memoryUsagePercent -gt 80) {
            Write-Log "WARN" "内存使用率较高: $memoryUsagePercent%"
            Record-Diagnosis "memory_usage" "WARNING" "内存使用率较高: $memoryUsagePercent%"
        } else {
            Write-Log "DEBUG" "内存使用正常: $memoryUsagePercent%"
            Record-Diagnosis "memory_usage" "PASSED" "内存使用正常: $memoryUsagePercent%"
        }
    } catch {
        Write-Log "ERROR" "检查内存使用时出错: $($_.Exception.Message)"
    }
}

# 检查网络连接
function Test-NetworkConnectivity {
    Write-Log "INFO" "检查网络连接..."
    
    # 检查本地回环
    try {
        $loopback = Test-NetConnection -ComputerName "127.0.0.1" -InformationLevel Quiet
        if ($loopback) {
            Write-Log "DEBUG" "本地回环连接正常"
            Record-Diagnosis "network_loopback" "PASSED" "本地回环连接正常"
        } else {
            Write-Log "ERROR" "本地回环连接失败"
            Record-Diagnosis "network_loopback" "FAILED" "本地回环连接失败" "Repair-NetworkLoopback"
        }
    } catch {
        Write-Log "ERROR" "本地回环连接测试失败: $($_.Exception.Message)"
    }
    
    # 检查外网连接
    try {
        $external = Test-NetConnection -ComputerName "8.8.8.8" -InformationLevel Quiet
        if ($external) {
            Write-Log "DEBUG" "外网连接正常"
            Record-Diagnosis "network_external" "PASSED" "外网连接正常"
        } else {
            Write-Log "WARN" "外网连接失败"
            Record-Diagnosis "network_external" "FAILED" "外网连接失败" "Test-NetworkConfig"
        }
    } catch {
        Write-Log "WARN" "外网连接测试失败: $($_.Exception.Message)"
    }
    
    # 检查DNS解析
    try {
        $dns = Resolve-DnsName -Name "google.com" -ErrorAction SilentlyContinue
        if ($dns) {
            Write-Log "DEBUG" "DNS解析正常"
            Record-Diagnosis "network_dns" "PASSED" "DNS解析正常"
        } else {
            Write-Log "WARN" "DNS解析失败"
            Record-Diagnosis "network_dns" "FAILED" "DNS解析失败" "Repair-DNSConfig"
        }
    } catch {
        Write-Log "WARN" "DNS解析测试失败: $($_.Exception.Message)"
    }
}

# 检查应用健康状态
function Test-ApplicationHealth {
    Write-Log "INFO" "检查应用健康状态..."
    
    # 检查应用进程
    $nodeProcess = Get-Process -Name "node" -ErrorAction SilentlyContinue | Where-Object { $_.CommandLine -like "*app.js*" }
    if ($nodeProcess) {
        Write-Log "DEBUG" "应用进程运行正常"
        Record-Diagnosis "app_process" "PASSED" "应用进程运行正常"
    } else {
        Write-Log "ERROR" "应用进程未运行"
        Record-Diagnosis "app_process" "FAILED" "应用进程未运行" "Restart-Application"
    }
    
    # 检查健康检查端点
    $maxAttempts = 5
    $attempt = 1
    $healthOk = $false
    
    while ($attempt -le $maxAttempts) {
        try {
            $response = Invoke-WebRequest -Uri "http://localhost/health" -UseBasicParsing -TimeoutSec 5
            if ($response.StatusCode -eq 200) {
                $healthOk = $true
                break
            }
        } catch {
            # 继续尝试
        }
        $attempt++
        Start-Sleep -Seconds 1
    }
    
    if ($healthOk) {
        Write-Log "SUCCESS" "应用健康检查通过"
        Record-Diagnosis "app_health" "PASSED" "应用健康检查通过"
    } else {
        Write-Log "ERROR" "应用健康检查失败"
        Record-Diagnosis "app_health" "FAILED" "应用健康检查失败" "Restart-Application"
    }
}

# 检查前端文件
function Test-FrontendFiles {
    Write-Log "INFO" "检查前端文件..."
    
    $frontendFiles = @(
        "$Script:InstallPath\public\js\app.js",
        "$Script:InstallPath\public\css\style.css"
    )
    
    $missingFiles = @()
    
    foreach ($file in $frontendFiles) {
        if (-not (Test-Path $file)) {
            $missingFiles += (Split-Path $file -Leaf)
        }
    }
    
    if ($missingFiles.Count -eq 0) {
        Write-Log "DEBUG" "前端文件完整"
        Record-Diagnosis "frontend_files" "PASSED" "前端文件完整"
    } else {
        Write-Log "WARN" "缺少前端文件: $($missingFiles -join ', ')"
        Record-Diagnosis "frontend_files" "FAILED" "缺少前端文件: $($missingFiles -join ', ')" "New-MissingFrontendFiles"
    }
}

# 检查项目依赖
function Test-ProjectDependencies {
    Write-Log "INFO" "检查项目依赖..."
    
    if (Test-Path "$Script:InstallPath\package.json") {
        if (Test-Path "$Script:InstallPath\node_modules") {
            Write-Log "DEBUG" "项目依赖已安装"
            Record-Diagnosis "project_dependencies" "PASSED" "项目依赖已安装"
        } else {
            Write-Log "WARN" "项目依赖未安装"
            Record-Diagnosis "project_dependencies" "FAILED" "项目依赖未安装" "Install-ProjectDependencies"
        }
    } else {
        Write-Log "ERROR" "package.json文件不存在"
        Record-Diagnosis "project_dependencies" "FAILED" "package.json文件不存在" "Install-ProjectDependencies"
    }
}

# 修复函数：重启Windows服务
function Restart-WindowsService {
    param([string]$ServiceName)
    
    Write-Log "FIX" "重启服务: $ServiceName"
    
    try {
        Restart-Service -Name $ServiceName -Force
        Start-Sleep -Seconds 5
        
        $service = Get-Service -Name $ServiceName
        if ($service.Status -eq "Running") {
            Write-Log "SUCCESS" "服务 $ServiceName 重启成功"
            $Script:IssuesFixed++
            return $true
        } else {
            Write-Log "ERROR" "服务 $ServiceName 重启失败"
            return $false
        }
    } catch {
        Write-Log "ERROR" "重启服务 $ServiceName 时出错: $($_.Exception.Message)"
        return $false
    }
}

# 修复函数：修复端口问题
function Repair-PortIssue {
    param([int]$Port)
    
    Write-Log "FIX" "修复端口 $Port 问题"
    
    switch ($Port) {
        80 {
            Restart-WindowsService "W3SVC"
        }
        3000 {
            Restart-WindowsService $Script:ServiceName
        }
        3306 {
            Restart-WindowsService "MySQL80"
        }
    }
}

# 修复函数：重启应用
function Restart-Application {
    Write-Log "FIX" "重启应用服务"
    
    if (Restart-WindowsService $Script:ServiceName) {
        Start-Sleep -Seconds 10
        $service = Get-Service -Name $Script:ServiceName
        if ($service.Status -eq "Running") {
            Write-Log "SUCCESS" "应用服务重启成功"
            $Script:IssuesFixed++
        } else {
            Write-Log "ERROR" "应用服务重启后仍未运行"
        }
    } else {
        Write-Log "ERROR" "应用服务重启失败"
    }
}

# 修复函数：清理磁盘空间
function Invoke-DiskCleanup {
    param([string]$Drive)
    
    Write-Log "FIX" "清理磁盘空间: $Drive"
    
    try {
        # 清理临时文件
        $tempPaths = @(
            "$env:TEMP\*",
            "$env:WINDIR\Temp\*",
            "$env:LOCALAPPDATA\Temp\*"
        )
        
        foreach ($tempPath in $tempPaths) {
            try {
                Remove-Item -Path $tempPath -Recurse -Force -ErrorAction SilentlyContinue
            } catch {
                # 忽略删除错误
            }
        }
        
        # 运行磁盘清理
        Start-Process -FilePath "cleanmgr.exe" -ArgumentList "/sagerun:1" -Wait -WindowStyle Hidden
        
        Write-Log "SUCCESS" "磁盘空间清理完成"
        $Script:IssuesFixed++
    } catch {
        Write-Log "ERROR" "磁盘清理失败: $($_.Exception.Message)"
    }
}

# 修复函数：修复数据库架构
function Repair-DatabaseSchema {
    Write-Log "FIX" "修复数据库架构问题"
    
    # 读取数据库配置
    $envFile = "$Script:InstallPath\.env"
    if (-not (Test-Path $envFile)) {
        Write-Log "ERROR" "无法读取数据库配置"
        return $false
    }
    
    try {
        $envContent = Get-Content $envFile
        $dbHost = ($envContent | Where-Object { $_ -match "^DB_HOST=" }) -replace "DB_HOST=", ""
        $dbUser = ($envContent | Where-Object { $_ -match "^DB_USER=" }) -replace "DB_USER=", ""
        $dbPassword = ($envContent | Where-Object { $_ -match "^DB_PASSWORD=" }) -replace "DB_PASSWORD=", ""
        $dbName = ($envContent | Where-Object { $_ -match "^DB_NAME=" }) -replace "DB_NAME=", ""
        
        # 创建数据库架构修复SQL
        $sqlScript = @"
-- 检查并创建完整的数据库架构

-- 创建笔记表（如果不存在）
CREATE TABLE IF NOT EXISTS notes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    content LONGTEXT,
    tags JSON,
    is_public TINYINT(1) DEFAULT 0,
    is_deleted TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL DEFAULT NULL,
    INDEX idx_user_id (user_id),
    INDEX idx_title (title),
    INDEX idx_is_deleted (is_deleted),
    INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建用户表（如果不存在）
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    nickname VARCHAR(100) DEFAULT NULL,
    role ENUM('admin', 'user') DEFAULT 'user',
    avatar VARCHAR(500) DEFAULT NULL,
    storage_used BIGINT DEFAULT 0,
    storage_limit BIGINT DEFAULT 32212254720,
    is_active TINYINT(1) DEFAULT 1,
    last_login_at TIMESTAMP NULL DEFAULT NULL,
    last_login_ip VARCHAR(45) DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_email (email),
    INDEX idx_role (role),
    INDEX idx_is_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建文件表（如果不存在）
CREATE TABLE IF NOT EXISTS files (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    filename VARCHAR(255) NOT NULL,
    original_name VARCHAR(255) NOT NULL,
    file_path VARCHAR(500) NOT NULL,
    file_size BIGINT NOT NULL,
    mime_type VARCHAR(100) NOT NULL,
    is_deleted TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_filename (filename),
    INDEX idx_is_deleted (is_deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建标签表（如果不存在）
CREATE TABLE IF NOT EXISTS tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    name VARCHAR(50) NOT NULL,
    color VARCHAR(7) DEFAULT '#007bff',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_user_tag (user_id, name),
    INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建笔记标签关联表（如果不存在）
CREATE TABLE IF NOT EXISTS note_tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    note_id INT NOT NULL,
    tag_id INT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_note_tag (note_id, tag_id),
    INDEX idx_note_id (note_id),
    INDEX idx_tag_id (tag_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建设置表（如果不存在）
CREATE TABLE IF NOT EXISTS settings (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    setting_key VARCHAR(100) NOT NULL,
    setting_value TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY unique_user_setting (user_id, setting_key),
    INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建活动日志表（如果不存在）
CREATE TABLE IF NOT EXISTS activity_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    action VARCHAR(100) NOT NULL,
    resource_type VARCHAR(50),
    resource_id INT,
    details JSON,
    ip_address VARCHAR(45),
    user_agent TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_action (action),
    INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 创建默认管理员用户（如果不存在）
INSERT IGNORE INTO users (email, password, nickname, role, is_active, created_at) 
VALUES ('admin@123.com', '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', '管理员', 'admin', 1, NOW());
"@
        
        # 将SQL脚本写入临时文件
        $tempSqlFile = "$env:TEMP\fix_database_schema.sql"
        $sqlScript | Out-File -FilePath $tempSqlFile -Encoding UTF8
        
        # 执行数据库修复
        $result = & mysql -h $dbHost -u $dbUser -p"$dbPassword" $dbName -e "source $tempSqlFile" 2>$null
        
        if ($LASTEXITCODE -eq 0) {
            Write-Log "SUCCESS" "数据库架构修复完成"
            $Script:IssuesFixed++
            Remove-Item -Path $tempSqlFile -Force -ErrorAction SilentlyContinue
            return $true
        } else {
            Write-Log "ERROR" "数据库架构修复失败"
            Remove-Item -Path $tempSqlFile -Force -ErrorAction SilentlyContinue
            return $false
        }
    } catch {
        Write-Log "ERROR" "数据库架构修复失败: $($_.Exception.Message)"
        return $false
    }
}

# 修复函数：创建缺失的前端文件
function New-MissingFrontendFiles {
    Write-Log "FIX" "创建缺失的前端文件"
    
    try {
        # 创建public目录结构
        $publicDirs = @(
            "$Script:InstallPath\public\js",
            "$Script:InstallPath\public\css",
            "$Script:InstallPath\public\static\image"
        )
        
        foreach ($dir in $publicDirs) {
            if (-not (Test-Path $dir)) {
                New-Item -ItemType Directory -Path $dir -Force | Out-Null
            }
        }
        
        # 创建基本的JavaScript文件
        $appJsPath = "$Script:InstallPath\public\js\app.js"
        if (-not (Test-Path $appJsPath)) {
            $appJsContent = @"
// 基本应用配置
const API_BASE = '/api';

// 工具函数
const utils = {
    // 发送API请求
    async request(url, options = {}) {
        const token = localStorage.getItem('token');
        const headers = {
            'Content-Type': 'application/json',
            ...options.headers
        };
        
        if (token) {
            headers.Authorization = `Bearer `${token}`;
        }
        
        const response = await fetch(API_BASE + url, {
            ...options,
            headers
        });
        
        return response.json();
    },
    
    // 显示消息
    showMessage(message, type = 'info') {
        console.log(`[`${type.toUpperCase()}`] `${message}``);
    }
};

// 导出到全局
window.utils = utils;
"@
            $appJsContent | Out-File -FilePath $appJsPath -Encoding UTF8
        }
        
        # 创建基本的CSS文件
        $styleCssPath = "$Script:InstallPath\public\css\style.css"
        if (-not (Test-Path $styleCssPath)) {
            $styleCssContent = @"
/* 基本样式 */
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    margin: 0;
    padding: 20px;
    background-color: #f5f5f5;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.btn {
    padding: 8px 16px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
}

.btn-primary {
    background-color: #007bff;
    color: white;
}

.btn-primary:hover {
    background-color: #0056b3;
}
"@
            $styleCssContent | Out-File -FilePath $styleCssPath -Encoding UTF8
        }
        
        Write-Log "SUCCESS" "前端文件创建完成"
        $Script:IssuesFixed++
        return $true
    } catch {
        Write-Log "ERROR" "前端文件创建失败: $($_.Exception.Message)"
        return $false
    }
}

# 修复函数：安装项目依赖
function Install-ProjectDependencies {
    Write-Log "FIX" "安装项目依赖"
    
    try {
        Push-Location $Script:InstallPath
        
        $result = & npm install --production 2>$null
        
        if ($LASTEXITCODE -eq 0) {
            Write-Log "SUCCESS" "项目依赖安装完成"
            $Script:IssuesFixed++
            return $true
        } else {
            Write-Log "ERROR" "项目依赖安装失败"
            return $false
        }
    } catch {
        Write-Log "ERROR" "项目依赖安装失败: $($_.Exception.Message)"
        return $false
    } finally {
        Pop-Location
    }
}

# 修复函数：测试API功能
function Test-APIFunctionality {
    Write-Log "FIX" "测试API功能"
    
    # 等待服务完全启动
    Start-Sleep -Seconds 5
    
    try {
        # 测试登录API
        $loginData = @{
            email = "admin@123.com"
            password = "admin123"
        } | ConvertTo-Json
        
        $loginResponse = Invoke-RestMethod -Uri "http://localhost:3000/api/auth/login" -Method Post -Body $loginData -ContentType "application/json" -TimeoutSec 10
        
        if ($loginResponse.success) {
            Write-Log "SUCCESS" "登录API测试成功"
            
            # 提取token
            $token = $loginResponse.token
            
            if ($token) {
                # 测试笔记API
                $headers = @{
                    "Authorization" = "Bearer $token"
                }
                
                $statsResponse = Invoke-RestMethod -Uri "http://localhost:3000/api/notes/stats" -Method Get -Headers $headers -TimeoutSec 10
                
                if ($statsResponse.success) {
                    Write-Log "SUCCESS" "笔记统计API测试成功"
                    $Script:IssuesFixed++
                    return $true
                } else {
                    Write-Log "WARN" "笔记统计API测试失败"
                }
            }
        } else {
            Write-Log "WARN" "登录API测试失败"
        }
    } catch {
        Write-Log "WARN" "API功能测试失败: $($_.Exception.Message)"
    }
    
    return $false
}

# 生成诊断报告
function New-DiagnosisReport {
    Write-Log "INFO" "生成诊断报告..."
    
    $timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
    $hostname = $env:COMPUTERNAME
    
    $report = @{
        diagnosis_id = "diag_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
        timestamp = $timestamp
        hostname = $hostname
        platform = @{
            os = "Windows"
            version = (Get-CimInstance Win32_OperatingSystem).Version
            edition = (Get-CimInstance Win32_OperatingSystem).Caption
        }
        summary = @{
            total_checks = $Script:DiagnosisResults.Count
            issues_found = $Script:IssuesFound
            issues_fixed = $Script:IssuesFixed
            auto_fix_enabled = $AutoFix
        }
        checks = @{}
    }
    
    foreach ($checkName in $Script:DiagnosisResults.Keys) {
        $result = $Script:DiagnosisResults[$checkName]
        $report.checks[$checkName] = @{
            status = $result.Status
            details = $result.Details
        }
    }
    
    $report | ConvertTo-Json -Depth 10 | Out-File -FilePath $Script:ReportFile -Encoding UTF8
    
    Write-Log "SUCCESS" "诊断报告已生成: $Script:ReportFile"
}

# 显示诊断结果摘要
function Show-Summary {
    Write-Host ""
    Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor $Script:Colors.Cyan
    Write-Host "║                    诊断结果摘要                                ║" -ForegroundColor $Script:Colors.Cyan
    Write-Host "║                 Diagnosis Summary                            ║" -ForegroundColor $Script:Colors.Cyan
    Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor $Script:Colors.Cyan
    Write-Host ""
    
    Write-Log "INFO" "诊断完成！"
    Write-Host ""
    Write-Host "统计信息:" -ForegroundColor $Script:Colors.Cyan
    Write-Host "  总检查项: " -NoNewline -ForegroundColor $Script:Colors.White
    Write-Host $Script:DiagnosisResults.Count -ForegroundColor $Script:Colors.Yellow
    Write-Host "  发现问题: " -NoNewline -ForegroundColor $Script:Colors.White
    Write-Host $Script:IssuesFound -ForegroundColor $Script:Colors.Red
    Write-Host "  已修复问题: " -NoNewline -ForegroundColor $Script:Colors.White
    Write-Host $Script:IssuesFixed -ForegroundColor $Script:Colors.Green
    Write-Host "  剩余问题: " -NoNewline -ForegroundColor $Script:Colors.White
    Write-Host ($Script:IssuesFound - $Script:IssuesFixed) -ForegroundColor $Script:Colors.Yellow
    Write-Host ""
    
    if ($Script:IssuesFound -gt 0) {
        Write-Host "问题详情:" -ForegroundColor $Script:Colors.Cyan
        foreach ($checkName in $Script:DiagnosisResults.Keys) {
            $result = $Script:DiagnosisResults[$checkName]
            
            if ($result.Status -eq "FAILED") {
                Write-Host "  ✗ $checkName`: $($result.Details)" -ForegroundColor $Script:Colors.Red
            } elseif ($result.Status -eq "WARNING") {
                Write-Host "  ⚠ $checkName`: $($result.Details)" -ForegroundColor $Script:Colors.Yellow
            }
        }
        Write-Host ""
    }
    
    Write-Host "报告文件: " -NoNewline -ForegroundColor $Script:Colors.Cyan
    Write-Host $Script:ReportFile -ForegroundColor $Script:Colors.Yellow
    Write-Host "日志文件: " -NoNewline -ForegroundColor $Script:Colors.Cyan
    Write-Host $Script:LogFile -ForegroundColor $Script:Colors.Yellow
    Write-Host ""
    
    if (($Script:IssuesFound -gt $Script:IssuesFixed) -and (-not $AutoFix)) {
        Write-Host "提示: 使用 -AutoFix 参数可以自动修复发现的问题" -ForegroundColor $Script:Colors.Yellow
        Write-Host ""
    }
}

# 执行修复操作
function Invoke-Repairs {
    if (-not $AutoFix -or $Script:RepairActions.Count -eq 0) {
        return
    }
    
    Write-Log "INFO" "开始自动修复..."
    Write-Host ""
    
    foreach ($checkName in $Script:RepairActions.Keys) {
        $result = $Script:DiagnosisResults[$checkName]
        
        if ($result.Status -eq "FAILED") {
            $repairAction = $Script:RepairActions[$checkName]
            Write-Log "INFO" "修复 $checkName..."
            
            # 执行修复操作
            try {
                Invoke-Expression $repairAction
            } catch {
                Write-Log "ERROR" "修复 $checkName 时出错: $($_.Exception.Message)"
            }
        }
    }
    
    Write-Log "SUCCESS" "自动修复完成"
}

# 主诊断函数
function Start-Diagnosis {
    Write-Log "INFO" "开始系统诊断..."
    Write-Host ""
    
    # 执行各项检查
    Test-WindowsServices
    Test-PortListening
    Test-ConfigurationFiles
    Test-DatabaseConnection
    Test-FilePermissions
    Test-DiskSpace
    Test-MemoryUsage
    Test-NetworkConnectivity
    Test-ApplicationHealth
    
    # 检查前端文件
    Test-FrontendFiles
    
    # 检查项目依赖
    Test-ProjectDependencies
    
    # 执行修复（如果启用）
    Invoke-Repairs
    
    # 生成报告
    New-DiagnosisReport
    
    # 显示摘要
    Show-Summary
}

# 显示横幅
function Show-Banner {
    Write-Host @"
╔══════════════════════════════════════════════════════════════╗
║                个人云笔记诊断修复工具                          ║
║           Personal Cloud Notes Diagnosis Tool               ║
║                                                              ║
║  版本: 2.0                                                   ║
║  功能: 智能诊断、自动修复、详细报告                            ║
╚══════════════════════════════════════════════════════════════╝
"@ -ForegroundColor $Script:Colors.Cyan
}

# 主函数
function Main {
    # 显示帮助
    if ($Help) {
        Show-Help
        return
    }
    
    # 显示横幅
    Show-Banner
    
    # 检查管理员权限
    $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
    if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        Write-Log "ERROR" "此脚本需要管理员权限运行"
        Write-Log "INFO" "请以管理员身份运行PowerShell，然后执行此脚本"
        exit 1
    }
    
    # 创建日志文件
    try {
        New-Item -ItemType File -Path $Script:LogFile -Force | Out-Null
    } catch {
        Write-Host "无法创建日志文件: $Script:LogFile" -ForegroundColor $Script:Colors.Red
    }
    
    # 运行诊断
    Start-Diagnosis
    
    # 返回适当的退出码
    if ($Script:IssuesFound -eq 0) {
        exit 0
    } elseif ($Script:IssuesFixed -eq $Script:IssuesFound) {
        exit 0
    } else {
        exit 1
    }
}

# 脚本入口点
if ($MyInvocation.InvocationName -ne '.') {
    Main
}